//****************************************************
// Porman Project 2
// Filename: CFXObject.cpp
// Date: 2008/10/02
// Author: KengYu Lin
// Modify:
//****************************************************
#include <string>
#include "CRenderDevice.h"
#include "CFXObject.h"
#include "CTextureObject.h"

namespace Porman
{

namespace GL
{
//----------------------------------
// class CPass
//----------------------------------
CFXObject::CTechnique::CPass::CPass( CGpass Pass ) :
m_vectSemantic()
{
    m_cgPass = Pass;
}

CFXObject::CTechnique::CPass::~CPass( void )
{
    m_vectSemantic.clear();
}

const char* CFXObject::CTechnique::CPass::getPassName( void )
{
    return cgGetPassName( m_cgPass );
}

std::string CFXObject::CTechnique::CPass::getCode( EPassDomain enumDomain, EPassCodeType enumCodeType )
{
    std::string sCode = "";
    CGdomain cgDomain = CG_VERTEX_DOMAIN;
    switch( enumDomain )
    {
    case E_PASSDOMAIN_VERTEX:
        cgDomain = CG_VERTEX_DOMAIN;
        break;
    case E_PASSDOMAIN_GEOMETRY:
        cgDomain = CG_GEOMETRY_DOMAIN;
        break;
    case E_PASSDOMAIN_PIXEL:
        cgDomain = CG_FRAGMENT_DOMAIN;
        break;
    }

    CGprogram cgProgram = cgGetPassProgram( m_cgPass, cgDomain );
    if( cgProgram )
    {
        switch( enumCodeType )
        {
        case E_PASSCODE_SOURCE:
            sCode = cgGetProgramString( cgProgram, CG_PROGRAM_SOURCE );
        case E_PASSCODE_ENTRY:
            sCode = cgGetProgramString( cgProgram, CG_PROGRAM_ENTRY );
        case E_PASSCODE_COMPILEDSOURCE:
            if( cgIsProgramCompiled( cgProgram ) ? true : false ) sCode = cgGetProgramString( cgProgram, CG_COMPILED_PROGRAM );
            break;
        }
    }

    return sCode;
}

void CFXObject::CTechnique::CPass::_enableVaryingShaderParameters( void )
{
    m_vectSemantic.clear();
    CGprogram cgProgram = cgGetPassProgram( m_cgPass, CG_VERTEX_DOMAIN );
    CGparameter cgParam = cgGetFirstLeafParameter( cgProgram, CG_PROGRAM );
    while( cgParam )
    {
        if( cgIsParameterReferenced( cgParam ) && cgGetParameterDirection( cgParam ) == CG_IN  )
        {
            std::string sSemantic = cgGetParameterSemantic( cgParam );
            if( sSemantic != "" )
            {
                SSemantic semantic( sSemantic.c_str(), cgParam );
                m_vectSemantic.push_back( semantic );
            }
        }
        cgParam = cgGetNextLeafParameter( cgParam );
    }
}

void CFXObject::CTechnique::CPass::_disableVaryingShaderParameters( void )
{
    int iSizeSemantic = static_cast<int>( m_vectSemantic.size() );
    for( int k=0; k<iSizeSemantic; k++ )
    {
        if( m_vectSemantic[k].m_bEnable )
        {
            cgGLDisableClientState( m_vectSemantic[k].m_cgParam );
            m_vectSemantic[k].m_bEnable = false;
        }
    }
}

int CFXObject::CTechnique::CPass::_getSemanticSize( void )
{
    return static_cast<int>(m_vectSemantic.size());
}

SSemantic* CFXObject::CTechnique::CPass::_getSemantic( int iIndex )
{
    if( iIndex < 0 || iIndex >= _getSemanticSize() )
    {
        assert(0);         
        return NULL;
    }
    else
        return &m_vectSemantic[iIndex];
}

//----------------------------------
// class CTechnique
//----------------------------------
CFXObject::CTechnique::CTechnique( CGtechnique Tech )
{
    m_cgTechnique = Tech;
    CGpass cgPass = cgGetFirstPass( m_cgTechnique );
    while( cgPass )
    {
        CPass* pPass = new CPass( cgPass );
        pPass->m_pParentTech = this;
        m_vectPasses.push_back( pPass );

        cgPass = cgGetNextPass( cgPass );
    }
}

CFXObject::CTechnique::~CTechnique( void )
{
    int iCount = static_cast<int>( m_vectPasses.size() );
    for( int i = 0; i<iCount; i++ )
    {
        SAFEDELETE( m_vectPasses[i] );
    }

    m_vectPasses.clear();
}

CFXObject::CTechnique::CPass* CFXObject::CTechnique::getNamedPass( const char* sName )
{
    int iCount = static_cast<int>( m_vectPasses.size() );
    for( int i = 0; i<iCount; i++ )
    {
        std::string s1( sName ); std::string s2( m_vectPasses[i]->getPassName() );
        if( s1 == s2 )
            return m_vectPasses[i];
    }

    return NULL;
}

CFXObject::CTechnique::CPass* CFXObject::CTechnique::getIndexedPass( int iIndex )
{
    return m_vectPasses[iIndex];
}

int CFXObject::CTechnique::getNumOfPass( void )
{
    return static_cast<int>( m_vectPasses.size() );
}

const char* CFXObject::CTechnique::getTechName( void )
{
    return cgGetTechniqueName( m_cgTechnique );
}

ERESULT CFXObject::CTechnique::validateTechs( std::string* pMsg )
{
    if( cgValidateTechnique( m_cgTechnique ) == CG_FALSE )
    {
        ERESULT enumResult = E_INVALID_OPERATION;
        switch( cgGetError() )
        {
        case CG_COMPILER_ERROR:
            {
                CGcontext* pContextRef = m_pParentFXObj->m_pDeviceRef->_getShaderContext();
                if( pMsg ) (*pMsg) = std::string( cgGetLastListing( (*pContextRef) ) );
                enumResult =  E_COMPILE_ERROR;
                break;
            }
        default:
            enumResult = E_INVALID_OPERATION; 
            break;
        }

        assert(0);
        return enumResult;
    }

    int iTotal = getNumOfPass();
    for( int i=0; i<iTotal; i++ )
        getIndexedPass(i)->_enableVaryingShaderParameters();

    return E_SUCCESS;
}

bool CFXObject::CTechnique::isValidated( void )
{
    return (cgIsTechniqueValidated( m_cgTechnique ) ? true : false);
}

//----------------------------------
// class CFXObject
//----------------------------------
CFXObject::CFXObject( CRenderDevice* pDevice ) :
CBaseObject(pDevice),
m_uiParamID(0),
m_uiSamplerParamID(0),
m_vectTechs(),
m_vectSamplerParams(),
m_vectInstParams()
{
    setName("Non");
    m_iNumOfFXObj++;
}

CFXObject::~CFXObject( void )
{
    _clearParam();

    int iSize = static_cast<int>( m_vectTechs.size() );
    for( int i = 0; i<iSize; i++ )
    {
        SAFEDELETE( m_vectTechs[i] );
    }
    m_vectTechs.clear();

    cgDestroyEffect( m_cgEffect );
    m_iNumOfFXObj--;
}

CFXObject::CTechnique* CFXObject::getNamedTech( const char* sName )
{
    if( sName )
    {
        int iCount = static_cast<int>( m_vectTechs.size() );
        for( int i = 0; i<iCount; i++ )
        {
            std::string s1( sName ); std::string s2( m_vectTechs[i]->getTechName() );
            if( s1 == s2 )
                return m_vectTechs[i];
        }
    }

    assert(0);
    return NULL;
}

CFXObject::CTechnique* CFXObject::getIndexedTech( int iIndex )
{
    if( !(iIndex < 0 || iIndex >= getNumOfTech()) )
        return m_vectTechs[iIndex];

    assert(0);
    return NULL;
}

int CFXObject::getNumOfTech( void )
{
    return static_cast<int>( m_vectTechs.size() );
}

ERESULT CFXObject::setArraySize( const HSHADERPARAM* pParam, const int& iSize )
{
    if( pParam && pParam->isVaild() )
    {
        cgSetArraySize( pParam->m_cgParam, iSize );
        return E_SUCCESS; 
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::setArrayMultiDimSize( const HSHADERPARAM* pParam, const int* pSize )
{
    if( pParam && pParam->isVaild() && pSize )
    {
        cgSetMultiDimArraySize( pParam->m_cgParam, pSize );
        return E_SUCCESS; 
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::setParameterFloat( const HSHADERPARAM* pParam, float fVal )
{
    ERESULT enumResult = E_INVALID_VALUE;
    if( pParam && pParam->isVaild() )
    {
        cgSetParameter1f( pParam->m_cgParam, fVal );
        switch( cgGetError() )
        {
        case CG_NO_ERROR:
            return E_SUCCESS;
        default:
            enumResult = E_INVALID_PARAMETER;
            break;
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setParameterFloatArrayRow( const HSHADERPARAM* pParam, unsigned int iNumElement, const float* fArray )
{
    ERESULT enumResult = E_INVALID_VALUE;
    if( pParam && pParam->isVaild() && fArray )
    {
        cgSetParameterValuefr( pParam->m_cgParam, iNumElement, fArray );
        switch( cgGetError() )
        {
        case CG_NO_ERROR:
            return E_SUCCESS;
        default:
            enumResult = E_INVALID_PARAMETER;
            break;
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setParameterFloatArrayCol( const HSHADERPARAM* pParam, unsigned int iNumElement, const float* fArray )
{
    ERESULT enumResult = E_INVALID_VALUE;
    if( pParam && pParam->isVaild() && fArray )
    {
        cgSetParameterValuefc( pParam->m_cgParam, iNumElement, fArray );
        switch( cgGetError() )
        {
        case CG_NO_ERROR:
            return E_SUCCESS;
        default:
            enumResult = E_INVALID_PARAMETER;
            break;
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setSampler( const HSHADERPARAM* pParam, CTextureBaseObject* pTextureObj )
{
    THREAD_CHECKING(m_pDeviceRef->getCurThreadID(), E_THREAD_ERROR);

    ERESULT enumResult = E_INVALID_VALUE;
    if( pParam && pParam->isVaild() && pTextureObj )
    {
        GLenum texEnum = cgGLGetTextureEnum( pParam->m_cgParam );
        glActiveTextureARB( texEnum );
        glBindTexture( pTextureObj->m_eType, pTextureObj->m_uiObjID );
        cgSetSamplerState( pParam->m_cgParam );

        CSamplerState Sampler;
        _getSamplerStateFromFX( pParam->m_cgParam, Sampler );
        pTextureObj->m_Sampler = Sampler;

        bool bCheck = false;
        int iCount = static_cast<int>( m_vectSamplerParams.size() );
        for( int i=0; i<iCount; i++ )
        {   
            if( m_vectSamplerParams[i].m_cgParam == pParam->m_cgParam )
            {   
                bCheck = true; 
                break;
            }
        }

        if( !bCheck )
            m_vectSamplerParams.push_back( (*pParam) );

        return E_SUCCESS;
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setSampler( const HSHADERPARAM* pParam, const CSamplerState* pSampler, CTextureBaseObject* pTextureObj )
{
    THREAD_CHECKING(m_pDeviceRef->getCurThreadID(), E_THREAD_ERROR);

    ERESULT enumResult = E_INVALID_VALUE;
    if( pParam && pParam->isVaild() && pTextureObj && pTextureObj->_setSamplerState( (*pSampler) ) == E_SUCCESS )
    {
        GLenum texEnum = cgGLGetTextureEnum( pParam->m_cgParam );
        glActiveTextureARB( texEnum );
        glBindTexture( pTextureObj->m_eType, pTextureObj->m_uiObjID );

        bool bCheck = false;
        int iCount = static_cast<int>( m_vectSamplerParams.size() );
        for( int i=0; i<iCount; i++ )
        {   
            if( m_vectSamplerParams[i].m_cgParam == pParam->m_cgParam )
            {   
                bCheck = true; 
                break;
            }
        }

        if( !bCheck )
            m_vectSamplerParams.push_back( (*pParam) );

        return E_SUCCESS;
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setArraySize( const char* sParam, const int& iSize )
{
    HSHADERPARAM param;
    if( getParameter( sParam, &param ) == E_SUCCESS )
    {
        return setArraySize( &param, iSize );
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::setArrayMultiDimSize( const char* sParam, const int* pSize )
{
    HSHADERPARAM param;
    if( getParameter( sParam, &param ) == E_SUCCESS )
    {
        return setArrayMultiDimSize( &param, pSize );
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::setParameterFloat( const char* sParam, float fVal )
{
    ERESULT enumResult = E_INVALID_VALUE;
    if( sParam )
    {
        CGparameter cgParam = cgGetNamedEffectParameter( m_cgEffect, sParam );
        if( cgParam )
        {
            cgSetParameter1f( cgParam, fVal );
            switch( cgGetError() )
            {
            case CG_NO_ERROR:
                return E_SUCCESS;
            default:
                enumResult = E_INVALID_PARAMETER;
                break;
            }
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setParameterFloatArrayRow( const char* sParam, unsigned int iNumElement, const float* fArray )
{
    ERESULT enumResult = E_INVALID_VALUE;
    if( sParam )
    {
        CGparameter cgParam = cgGetNamedEffectParameter( m_cgEffect, sParam );
        if( cgParam )
        {
            cgSetParameterValuefr( cgParam, iNumElement, fArray );
            switch( cgGetError() )
            {
            case CG_NO_ERROR:
                return E_SUCCESS;
            default:
                enumResult = E_INVALID_PARAMETER;
                break;
            }
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setParameterFloatArrayCol( const char* sParam, unsigned int iNumElement, const float* fArray )
{
    ERESULT enumResult = E_INVALID_VALUE;
    if( sParam )
    {
        CGparameter cgParam = cgGetNamedEffectParameter( m_cgEffect, sParam );
        if( cgParam )
        {
            cgSetParameterValuefc( cgParam, iNumElement, fArray );
            switch( cgGetError() )
            {
            case CG_NO_ERROR:
                return E_SUCCESS;
            default:
                enumResult = E_INVALID_PARAMETER;
                break;
            }
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setSampler( const char* sParam, CTextureBaseObject* pTextureObj )
{
    THREAD_CHECKING(m_pDeviceRef->getCurThreadID(), E_THREAD_ERROR);

    ERESULT enumResult = E_INVALID_VALUE;
    if( sParam && pTextureObj )
    {
        CGparameter cgParam = cgGetNamedEffectParameter( m_cgEffect, sParam );
        if( cgParam )
        {
            GLenum texEnum = cgGLGetTextureEnum( cgParam );
            glActiveTextureARB( texEnum );
            glBindTexture( pTextureObj->m_eType, pTextureObj->m_uiObjID );
            cgSetSamplerState( cgParam );
    
            CSamplerState Sampler;
            _getSamplerStateFromFX( cgParam, Sampler );
            pTextureObj->m_Sampler = Sampler;

            bool bCheck = false;
            int iCount = static_cast<int>( m_vectSamplerParams.size() );
            for( int i=0; i<iCount; i++ )
            {   
                if( m_vectSamplerParams[i].m_cgParam == cgParam )
                {   
                    bCheck = true; 
                    break;
                }
            }

            if( !bCheck )
            {
                HSHADERPARAM Param;
                Param.m_cgParam = cgParam;
                Param.m_sName = std::string( sParam );
                Param.m_iTexType = pTextureObj->getTexType();
                m_vectSamplerParams.push_back( Param );
            }

            return E_SUCCESS;
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setSampler( const char* sParam, const CSamplerState* pSampler, CTextureBaseObject* pTextureObj )
{
    THREAD_CHECKING(m_pDeviceRef->getCurThreadID(), E_THREAD_ERROR);

    ERESULT enumResult = E_INVALID_VALUE;
    if( sParam && pTextureObj && pTextureObj->_setSamplerState( (*pSampler) ) == E_SUCCESS )
    {
        CGparameter cgParam = cgGetNamedEffectParameter( m_cgEffect, sParam );
        if( cgParam )
        {
            GLenum texEnum = cgGLGetTextureEnum( cgParam );
            glActiveTextureARB( texEnum );
            glBindTexture( pTextureObj->m_eType, pTextureObj->m_uiObjID );

            bool bCheck = false;
            int iCount = static_cast<int>( m_vectSamplerParams.size() );
            for( int i=0; i<iCount; i++ )
            {   
                if( m_vectSamplerParams[i].m_cgParam == cgParam )
                {   
                    bCheck = true; 
                    break;
                }
            }

            if( !bCheck )
            {
                HSHADERPARAM Param;
                Param.m_cgParam = cgParam;
                Param.m_sName = std::string( sParam );
                Param.m_iTexType = pTextureObj->getTexType();
                m_vectSamplerParams.push_back( Param );
            }

            return E_SUCCESS;
        }
    }

    assert(0);
    return enumResult;
}

ERESULT CFXObject::setInterface( const char* sInterface, const HSHADERPARAM* pParam )
{
    if( sInterface && pParam && pParam->isVaild() )
    {
        CGparameter cgParam = cgGetNamedEffectParameter( m_cgEffect, sInterface );
        if( cgParam )
        {
            cgConnectParameter( pParam->m_cgParam, cgParam );
            return E_SUCCESS;
        }
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getParameter( const char* sParam, HSHADERPARAM* pParam )
{
    if( sParam && pParam )
    {
        CGparameter cgParam = cgGetNamedEffectParameter( m_cgEffect, sParam );
        if( cgParam )
        {
            pParam->m_cgParam = cgParam;
            pParam->m_sName = sParam;
        }
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getArrayDim( const char* sParam, int& iDim )
{
    iDim = 0;
    HSHADERPARAM param;
    if( getParameter( sParam, &param ) == E_SUCCESS )
    {
        return getArrayDim( &param, iDim );
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getArrayDim( HSHADERPARAM* pParam, int& iDim )
{
    iDim = 0;
    if( pParam )
    {
        iDim = cgGetArrayDimension( pParam->m_cgParam );
        return E_SUCCESS;
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getArraySize( const char* sParam, int iDim,int& iSize )
{
    iSize = 0;
    HSHADERPARAM param;
    if( getParameter( sParam, &param ) == E_SUCCESS )
    {
        getArraySize( &param, iDim, iSize );
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getArraySize( HSHADERPARAM* pParam, int iDim,int& iSize )
{
    iSize = 0;
    if( pParam )
    {
        iSize = cgGetArraySize( pParam->m_cgParam, iDim );
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getInstance( const char* sInstance, HSHADERPARAM* pParam )
{
    if( sInstance && pParam )
    {
        CGcontext* pContextRef = m_pDeviceRef->_getShaderContext();
        CGtype type = cgGetNamedUserType( m_cgEffect, sInstance );
        if( type != CG_UNKNOWN_TYPE )
        {
            CGparameter cgParam = cgCreateParameter( (*pContextRef), type );
            m_vectInstParams.push_back( cgParam );

            pParam->m_cgParam = cgParam;
            pParam->m_sName = sInstance;
            return E_SUCCESS;
        }
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getInstanceArray( const char* sInstance, int iLength, HSHADERPARAM* pParam )
{
    if( sInstance && pParam )
    {
        CGcontext* pContextRef = m_pDeviceRef->_getShaderContext();
        CGtype type = cgGetNamedUserType( m_cgEffect, sInstance );
        if( type != CG_UNKNOWN_TYPE )
        {
            CGparameter cgParam = cgCreateParameterArray( (*pContextRef), type, iLength );
            m_vectInstParams.push_back( cgParam );

            pParam->m_cgParam = cgParam;
            pParam->m_sName = sInstance;
            return E_SUCCESS;
        }
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getInstanceMultiDimArray( const char* sInstance, int iDim, const int* pLength, HSHADERPARAM* pParam )
{
    if( sInstance && pParam )
    {
        CGcontext* pContextRef = m_pDeviceRef->_getShaderContext();
        CGtype type = cgGetNamedUserType( m_cgEffect, sInstance );
        if( type != CG_UNKNOWN_TYPE )
        {
            CGparameter cgParam = cgCreateParameterMultiDimArray( (*pContextRef), type, iDim, pLength );
            m_vectInstParams.push_back( cgParam );

            pParam->m_cgParam = cgParam;
            pParam->m_sName = sInstance;
            return E_SUCCESS;
        }
    }

    assert(0);
    return E_INVALID_VALUE;
}

ERESULT CFXObject::getInstanceParam( const char* sInstance, const HSHADERPARAM* pInParam, HSHADERPARAM* pOutParam )
{
    if( sInstance && pInParam && pOutParam )
    {
        CGtype cgType = cgGetParameterType( pInParam->m_cgParam );
        if( cgType == CG_STRUCT )
        {
            std::string sInstParamName = pInParam->m_sName + "." + std::string( sInstance );
            CGparameter cgParam = cgGetFirstStructParameter( pInParam->m_cgParam );
            while( cgParam )
            {
                std::string sParamName = cgGetParameterName( cgParam );
                if( sInstParamName == sParamName )
                {
                    pOutParam->m_cgParam = cgParam;
                    pOutParam->m_sName = sInstance;
                    return E_SUCCESS;
                }
                cgParam = cgGetNextParameter( cgParam );
            }
        }
    }

    assert(0);
    return E_INVALID_VALUE;
}

void CFXObject::_disableAllSamplerParameters( void )
{
    int iCount = static_cast<int>( m_vectSamplerParams.size() );
    for( int i = 0; i<iCount; i++ )
    {
        GLenum texEnum = cgGLGetTextureEnum( m_vectSamplerParams[i].m_cgParam );
        glActiveTextureARB( texEnum );
        glBindTexture( m_vectSamplerParams[i].m_iTexType, 0 );
    }   
}

void CFXObject::_getSamplerStateFromFX( CGparameter cgParam, CSamplerState& Sampler )
{
    CGstateassignment sa = CG_ASSERT( cgGetFirstSamplerStateAssignment( cgParam ) );
    while( sa )
    {
        int iCount = 0;
        CGstate state = CG_ASSERT( cgGetStateAssignmentState( sa ) );
        std::string sStateName = CG_ASSERT( cgGetStateName( state ) );

        if( sStateName == "WrapS" )
        {
            const int* pVal = CG_ASSERT( cgGetIntStateAssignmentValues( sa, &iCount ) );
            if( iCount > 0 )
            {
                Sampler.m_eCoordWrap_s = static_cast<ECoordWrap>(pVal[0]);
            }
        }
        else if( sStateName == "WrapT" )
        {
            const int* pVal = CG_ASSERT( cgGetIntStateAssignmentValues( sa, &iCount ) );
            if( iCount > 0 )
            {
                Sampler.m_eCoordWrap_t = static_cast<ECoordWrap>(pVal[0]);
            }
        }
        else if( sStateName == "WrapR" )
        {
            const int* pVal = CG_ASSERT( cgGetIntStateAssignmentValues( sa, &iCount ) );
            if( iCount > 0 )
            {
                Sampler.m_eCoordWrap_r = static_cast<ECoordWrap>(pVal[0]);
            }
        }
        else if( sStateName == "MinFilter" )
        {
            const int* pVal = CG_ASSERT( cgGetIntStateAssignmentValues( sa, &iCount ) );
            if( iCount > 0 )
            {
                switch( pVal[0] )
                {
                case GL_NEAREST:
                    {
                        Sampler.m_eMinFilter = E_MIN_NEAREST;
                        Sampler.m_eMipMapFilter = E_MIPMAP_NON;
                    }
                    break;
                case GL_LINEAR:
                    {
                        Sampler.m_eMinFilter = E_MIN_LINEAR;
                        Sampler.m_eMipMapFilter = E_MIPMAP_NON;
                    }
                    break;
                case GL_NEAREST_MIPMAP_NEAREST:
                    {
                        Sampler.m_eMinFilter = E_MIN_NEAREST;
                        Sampler.m_eMipMapFilter = E_MIPMAP_NEAREST;
                    }
                    break;
                case GL_NEAREST_MIPMAP_LINEAR:
                    {
                        Sampler.m_eMinFilter = E_MIN_NEAREST;
                        Sampler.m_eMipMapFilter = E_MIPMAP_LINEAR;
                    }
                    break;
                case GL_LINEAR_MIPMAP_NEAREST:
                    {
                        Sampler.m_eMinFilter = E_MIN_LINEAR;
                        Sampler.m_eMipMapFilter = E_MIPMAP_NEAREST;
                    }
                    break;
                case GL_LINEAR_MIPMAP_LINEAR:
                    {
                        Sampler.m_eMinFilter = E_MIN_LINEAR;
                        Sampler.m_eMipMapFilter = E_MIPMAP_LINEAR;
                    }
                    break;
                }
            }
        }
        else if( sStateName == "MagFilter" )
        {
            const int* pVal = CG_ASSERT( cgGetIntStateAssignmentValues( sa, &iCount ) );
            if( iCount > 0 )
            {
                switch( pVal[0] )
                {
                case GL_NEAREST:
                    Sampler.m_eMagFilter = E_MAG_NEAREST;
                    break;
                case GL_LINEAR:
                    Sampler.m_eMagFilter = E_MAG_LINEAR;
                    break;
                }
            }
        }
        else if( sStateName == "MaxAnisotropy" )
        {
            const float* pVal = CG_ASSERT( cgGetFloatStateAssignmentValues( sa, &iCount ) );
            if( iCount > 0 )
            {
                Sampler.m_fAnisotropicVal = pVal[0];
            }
        }
        else if( sStateName == "BorderColor" )
        {
            const float* pVal = CG_ASSERT( cgGetFloatStateAssignmentValues( sa, &iCount ) );
            if( iCount > 0 )
            {
                Sampler.m_fBorderColor[0] = pVal[0];
                Sampler.m_fBorderColor[1] = pVal[1];
                Sampler.m_fBorderColor[2] = pVal[2];
                Sampler.m_fBorderColor[3] = pVal[3];
            }
        }

        sa = CG_ASSERT( cgGetNextStateAssignment( sa ) );
    }
}

void CFXObject::_clearParam( void )
{
    int iCount = static_cast<int>(m_vectInstParams.size());
    for( int i=0; i<iCount; i++ )
        cgDestroyParameter( m_vectInstParams[i] );

    m_vectInstParams.clear();
    m_vectSamplerParams.clear();
}

}//End namespace GL

}//End namespace Porman